﻿// Copyright richyp 2009
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Richyp.Bodger.Parser;
using Richyp.Bodger;
using System.Xml;

namespace Richyp.Bodger.UI {
    public partial class MainWindow : Form {
        private CodexFile codexFile = null;

        public CodexFile CodexFile {
            get {
                return this.codexFile;
            }
            set {
                this.codexFile = value;
            }
        }

        public MainWindow() {
            InitializeComponent();
            //this.TestMode();
            this.dataGridViewList.Paint += new PaintEventHandler(dataGridViewList_Paint);            
        }

        public MainWindow(string filename) {
            InitializeComponent();
            this.Load(filename);
            this.dataGridViewList.Paint += new PaintEventHandler(dataGridViewList_Paint);
        }

        public void TestMode() {
            BodgerFile bf = new BodgerFile();
            bf.Load(@"c:\Documents and Settings\richard.pickup\Documents\foo.abf", this.dataGridViewList, this);
        }

        public void LoadCodex(string name) {
            CodexParser parser = (CodexParser)ParserFactory.Instance.CreateParser(typeof(CodexParser));
            Console.WriteLine("Loading codex: " + name);
            this.codexFile = (CodexFile)parser.Parse(name);
            this.PopulateCodexEntries(true);
            this.PopulateTemplates();
            //this.toolStripButtonSystem.Image = this.codexFile.GameSystem.Icon;
           // this.toolStripButtonSystem.Visible = this.codexFile.GameSystem.Icon != null;
            this.toolStripLabelName.Text = this.codexFile.Name;

        }

        public void PopulateCodexEntries(bool clearDataGridViewList) {
            if (this.codexFile == null) {
                return;
            }
            bool showSpecial = showSpecialCharactersToolStripMenuItem.Checked;
            this.listViewCodexEntries.BeginUpdate();
            this.listViewCodexEntries.Items.Clear();
            this.listViewCodexEntries.Groups.Clear();
            foreach (CodexEntry entry in this.codexFile.CodexEntries) {
                ListViewGroup category = null;
                foreach (ListViewGroup group in this.listViewCodexEntries.Groups) {
                    if (group.Name == entry.Category) {
                        category = group;
                        break;
                    }
                }
                if (category == null) {
                    category = new ListViewGroup(entry.Category.Substring(2));
                    category.Name = entry.Category;
                    this.listViewCodexEntries.Groups.Add(category);
                }
                int total = 0;
                foreach (Unit unit in entry.Units) {
                    total += (unit.InitialQuantity * unit.GetTotalCost());
                }
                total += entry.CostOffset;
                ListViewItem item = new ListViewItem(entry.Name, category);
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, total.ToString()));
                item.Tag = entry;
                if (entry.Special) {
                    item.Font = new Font(item.Font, FontStyle.Bold);
                    item.ForeColor = Color.DarkBlue;
                    item.SubItems[0].ForeColor = Color.DarkBlue;
                }
                if (!entry.Special || (entry.Special && showSpecial)) {
                    this.listViewCodexEntries.Items.Add(item);
                }
            }
            this.listViewCodexEntries.EndUpdate();
            if (clearDataGridViewList)
            {
                this.dataGridViewList.Rows.Clear();
                this.dataGridViewAttributes.Rows.Clear();
                this.CreateHeaders();
            }
        }

        public void PopulateTemplates()
        {
            string path = Application.StartupPath + @"\Templates\";

            if (!System.IO.Directory.Exists(path))
                return;

            this.listViewTemplates.BeginUpdate();
            this.listViewTemplates.Items.Clear();
            this.listViewTemplates.Groups.Clear();

            string[] files = System.IO.Directory.GetFiles(path);
            List<ListViewItem> itemList = new List<ListViewItem>();
            Dictionary<string, ListViewGroup> groupDictionary = new Dictionary<string, ListViewGroup>();

            foreach (string file in files)
            {
                if(file.Substring(file.LastIndexOf(".") + 1) != "xml")
                    continue;

                XmlDocument templateDocument = new XmlDocument();
                templateDocument.LoadXml(System.IO.File.ReadAllText(file));

                if (templateDocument.DocumentElement.Name.ToLower() != "template")
                    continue;
                
                ListViewItem item = new ListViewItem();
                CodexEntry itemCodexEntry = null;

                foreach (XmlNode node in templateDocument.DocumentElement.ChildNodes)
                {
                    if (node.Name.ToLower() == "codex")
                    {
                        if (codexFile.Name != node.InnerText)
                            break;
                    }
                    
                    if (node.Name.ToLower() == "base")
                    {
                        // Find the codex entry
                        foreach (CodexEntry entry in codexFile.CodexEntries)
                        {
                            if (entry.Name == node.InnerText)
                                itemCodexEntry = entry;
                        }

                        if (itemCodexEntry == null)
                            break;

                        // Add a group if necessary
                        if (!groupDictionary.ContainsKey(node.InnerText))
                            groupDictionary.Add(node.InnerText, new ListViewGroup(node.InnerText));

                        item.Group = groupDictionary[node.InnerText];
                    }

                    if(node.Name.ToLower() == "label")
                        item.Name = node.InnerText;

                    if (node.Name.ToLower() == "entry")
                    {
                        if(itemCodexEntry == null)
                            break;

                        ListEntry listEntry  = new ListEntry(itemCodexEntry, this.dataGridViewList);
                        listEntry.Units.Clear();

                        foreach (XmlNode entryNode in node.ChildNodes)
                        {
                            if (entryNode.Name.ToLower() == "unit")
                            {
                                Unit unit = null;

                                foreach (XmlNode unitNode in entryNode.ChildNodes)
                                {
                                    if (unitNode.Name.ToLower() == "name")
                                    {
                                        unit = Unit.Copy(listEntry.BaseEntry.GetUnitByName(unitNode.InnerText));
                                        unit.Equipped.Clear();
                                    }

                                    if (unitNode.Name.ToLower() == "wargear")
                                    {
                                        if(unit == null)
                                            break;

                                        foreach (Equipment eq in unit.AllWargear)
                                        {
                                            if (eq.Wargear.Name == unitNode.InnerText)
                                                unit.Equipped.Add(eq);
                                        }
                                    }
                                }

                                listEntry.Units.Add(unit);
                            }
                            
                            item.Tag = (object)listEntry;
                        }
                    }
                }

                if (item.Name != "" && item.Tag != null && item.Group != null)
                {
                    item.Text = "     " + item.Name;
                    itemList.Add(item);
                }

            }

            foreach (ListViewGroup group in groupDictionary.Values)
            {
                listViewTemplates.Groups.Add(group);
            }

            foreach (ListViewItem item in itemList)
            {
                this.listViewTemplates.Items.Add(item);
            }

            this.listViewTemplates.EndUpdate();
        }

        private void listViewCodexEntries_ItemDrag(object sender, ItemDragEventArgs e) {
            if (e.Item != null) {
                ListViewItem item = (ListViewItem)e.Item;
                CodexEntry entry = (CodexEntry)item.Tag;
                this.DoDragDrop(entry, DragDropEffects.Copy);
            }
        }

        private void dataGridViewList_DragEnter(object sender, DragEventArgs e) {
            if (e.Data.GetDataPresent(typeof(CodexEntry))) {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void dataGridViewList_DragDrop(object sender, DragEventArgs e) {
            if (e.Data.GetDataPresent(typeof(CodexEntry))) {
                CodexEntry entry = (CodexEntry)e.Data.GetData(typeof(CodexEntry));
                if (this.ValidateNewEntry(entry)) {
                    //this.ValidateHeaders(entry.Category);
                    this.AddEntry(entry);
                }
            }
        }

        public void CreateHeaders() {
            List<string> categories = new List<string>();
            foreach (CodexEntry entry in this.codexFile.CodexEntries) {
                if (!categories.Contains(entry.Category)) {
                    categories.Add(entry.Category);
                }
            }
            categories.Sort();
            foreach (string category in categories) {
                CategoryRow row = new CategoryRow();
                row.Category = category;
                string filename = category.Substring(category.IndexOf(".") +1);
                string[] types = new string[] { ".png", ".gif", ".jpg", ".bmp" };
                foreach (string type in types) {
                    string path = Application.StartupPath + "/Data/Game System/";
                    path += codexFile.System + "/images/categories/";
                    path += filename + type;
                    if (System.IO.File.Exists(path)) {
                        row.Image = Image.FromFile(path);
                        break;
                    }
                }
                NiceRenderer header = new NiceRenderer(row.Category);
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                header = new NiceRenderer("");
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                header = new NiceRenderer("");
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                this.dataGridViewList.Rows.Add(row);
            }
            
        }

        void dataGridViewList_Paint(object sender, PaintEventArgs e) {
            int count = 0;
            foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                if( !(row is CategoryRow)) {
                    count++;
                    break;
                }
            }
            if (count == 0) {
                Brush b = new SolidBrush(Color.FromArgb(200, 0, 0, 0));
                e.Graphics.FillRectangle(b, e.ClipRectangle);
                int centerX = e.ClipRectangle.Width / 2;
                int centerY = e.ClipRectangle.Height / 2;
                string message = "No entries";
                Font f = new Font("Arial", 20, FontStyle.Bold);
                SizeF s = e.Graphics.MeasureString(message, f);
                centerX -= (int)(s.Width / 2);
                centerY -= (int)(s.Height / 2);
                e.Graphics.DrawString(message, f, Brushes.Black, centerX + 3, centerY + 3);
                e.Graphics.DrawString(message, f, Brushes.White, centerX, centerY);
            }
        }

        public void ValidateHeaders(string type) {
            bool exists = false;
            foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                if (row is CategoryRow && ((CategoryRow)row).Category == type) {
                    exists = true;
                    break;
                }
            }
            if (!exists) {
                CategoryRow row = new CategoryRow();
                row.Category = type;
                NiceRenderer header = new NiceRenderer(row.Category);
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                header = new NiceRenderer("");
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                header = new NiceRenderer("");
                header.IsCategoryRow = true;
                row.Cells.Add(header);
                this.dataGridViewList.Rows.Add(row);
            }
        }

        public bool ValidateNewEntry(CodexEntry entry) {

            return true;
        }

        public void AddEntry(CodexEntry entry) {
            ListEntry listEntry = new ListEntry(entry, this.dataGridViewList);

            AddEntry(listEntry, entry.Category);
        }

        public void AddEntry(ListEntry listEntry, string newCategory)
        {
            int offset = 1;
            int position = -1;
            foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                if (row is CategoryRow) {
                    string category = ((CategoryRow)row).Category;
                    if (position > -1 && category != newCategory) {
                        position = offset-1;
                        break;
                    }
                    if (category == newCategory)
                    {
                        position = offset;
                    }
                }
                offset++;
            }
            
            this.dataGridViewList.Rows.Insert(position, listEntry.Row);
            this.ValidateList();
        }

        public void ValidateList() {
            if (this.codexFile.GameSystem.Conditions.Count == 0) {
                this.toolStripLabelStatus.Text = "No conditions defined";
                this.toolStripLabelStatus.ToolTipText = this.codexFile.GameSystem.Name +
                    " does not define any army composition conditions";
            } else {
                Dictionary<string, int> counts = new Dictionary<string, int>();
                foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                    if( ! ( row is CategoryRow )) {
                        ListEntry entry = (ListEntry)row.Tag;
                        if (counts.ContainsKey(entry.BaseEntry.Category)) {
                            counts[entry.BaseEntry.Category]++;
                        } else {
                            counts[entry.BaseEntry.Category] = 1;
                        }
                    }
                }
                bool ok = true;
                string statusText = "";
                foreach (Condition condition in this.codexFile.GameSystem.Conditions) {
                    string category = condition.Category.Substring(
                        condition.Category.IndexOf(".")+1
                        );
                    if (!counts.ContainsKey(condition.Category)) {
                        counts[condition.Category] = 0;
                    }
                    int count = counts[condition.Category];
                    if (count < condition.Minimum ) {
                        ok = false;
                        statusText = "Not enough " + category + " entries";
                        break;
                    } else if (count > condition.Maximum) {
                        ok = false;
                        statusText = "Too many " + category + " entries";
                    }
                }
                if (statusText == "") {
                    statusText = "List is valid";
                }
                this.toolStripLabelStatus.ToolTipText = statusText;
                this.toolStripLabelStatus.Text = statusText;
                if (ok) {
                    this.toolStripLabelStatus.ForeColor = Color.Green;
                } else {
                    this.toolStripLabelStatus.ForeColor = Color.Red;
                }
            }
        }

        private void contextMenuStripList_Opening(object sender, CancelEventArgs e) {
            this.saveEntryAsTemplateToolStripMenuItem.Enabled = 
                this.deleteToolStripMenuItem.Enabled =
                this.dataGridViewList.SelectedRows.Count > 0 && !(this.dataGridViewList.SelectedRows[0] is CategoryRow);


            this.addToolStripMenuItem.DropDownItems.Clear();
            this.removeToolStripMenuItem.DropDownItems.Clear();

            if (this.dataGridViewList.SelectedRows.Count > 0 && !(this.dataGridViewList.SelectedRows[0] is CategoryRow)) {
                ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;

                if (entry.BaseEntry.AltCategory != null)
                {
                    this.toolStripButtonMove.Text = "Move to " + entry.AlternateCategory.Substring(2);
                    this.toolStripButtonMove.Visible = true;
                    this.toolStripSeparator7.Visible = true;
                }
                else
                {
                    this.toolStripButtonMove.Visible = false;
                    this.toolStripSeparator7.Visible = false;
                }

                foreach (Unit unit in entry.BaseEntry.Units) {
                    bool add = true;
                    foreach (Unit unit2 in entry.Units) {
                        if (unit.Name == unit2.Name) {
                            add = false;
                            break;
                        }
                    }
                    if (add) {
                        ToolStripMenuItem item = new ToolStripMenuItem(unit.Name);
                        item.Tag = unit;
                        item.Click += new EventHandler(item_Click);
                        this.addToolStripMenuItem.DropDownItems.Add(item);
                    }
                }
                this.addToolStripMenuItem.Enabled = this.addToolStripMenuItem.DropDownItems.Count > 0;
                foreach (Unit unit in entry.Units) {
                    if (unit.Minimum == 0) {
                        ToolStripMenuItem item = new ToolStripMenuItem(unit.Name);
                        item.Tag = unit;
                        item.Click += new EventHandler(item_Remove);
                        this.removeToolStripMenuItem.DropDownItems.Add(item);
                    }
                }
                this.removeToolStripMenuItem.Enabled = this.removeToolStripMenuItem.DropDownItems.Count > 0;
            } else {
                this.addToolStripMenuItem.Enabled = false;
            }
            
        }

        void item_Remove(object sender, EventArgs e) {
            Unit unit = ((Unit)((ToolStripMenuItem)sender).Tag);
            this.RemoveEntry(unit);
        }

        public void RemoveEntry(Unit unit) {
            ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
            List<Unit> remove = new List<Unit>();
            foreach (Unit existing in entry.Units) {
                if (existing.Name == unit.Name) {
                    remove.Add(existing);
                }
            }
            foreach (Unit x in remove) {
                entry.Units.Remove(x);
            }
            this.PopulateAttributes();
            entry.UpdateRow();
            this.ValidateList();
        }

        /// <summary>
        /// /// Executed when unittype is added to a unit from the context menu
        /// </summary>
        void item_Click(object sender, EventArgs e) {
            Unit unit = ((Unit)((ToolStripMenuItem)sender).Tag);
            ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
            Unit conflict = null;
            foreach (string exclusive in unit.ExclusiveList) {
                foreach (Unit existing in entry.Units) {
                    if (exclusive.ToUpper() == existing.Name.ToUpper()) {
                        conflict = existing;
                        break;
                    }
                }
            }
            if (conflict != null) {
                DialogResult dr = MessageBox.Show(
                    this,
                    "This entry already contains a " + conflict.Name + ".\n" +
                    "Would you like to replace it with a " + unit.Name + "?",
                    "Exclusive Entry",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question
                    );
                if (dr == DialogResult.Yes) {
                    entry.Units.Remove(conflict);
                } else {
                    return;
                }
            }
            entry.Units.Add(Unit.Copy(unit));
            this.PopulateAttributes();
            entry.UpdateRow();
            this.ValidateList();
        }

        private void dataGridViewList_MouseDown(object sender, MouseEventArgs e) {
            if (e.Button == MouseButtons.Right || e.Button == MouseButtons.Left) {
                DataGridView.HitTestInfo info = dataGridViewList.HitTest(e.X, e.Y);
                try {
                    if (info.ColumnIndex > -1 && info.RowIndex > -1) {
                        this.dataGridViewList.CurrentCell = this.dataGridViewList[info.ColumnIndex, info.RowIndex];
                        if (this.dataGridViewList.SelectedRows[0] is CategoryRow) {
                            this.dataGridViewList.CurrentCell = this.dataGridViewList.Rows[this.dataGridViewList.SelectedRows[0].Index + 1].Cells[0];
                            this.dataGridViewList.CurrentCell.Selected = true;
                            this.dataGridViewList.Refresh();
                        }
                    } else {
                        this.dataGridViewList.CurrentCell = null;
                    }
                } catch {
                    this.dataGridViewList.CurrentCell = null;
                }
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e) {
            this.DeleteSelected();
        }

        public void DeleteSelected() {
            foreach (DataGridViewRow row in this.dataGridViewList.SelectedRows) {
                this.dataGridViewList.Rows.Remove(row);
            }
            this.RecalculateTotal();
            this.ValidateList();
        }

        

        private void toolStripButtonSystem_Click(object sender, EventArgs e) {
            AboutSystemForm asf = new AboutSystemForm();
            asf.Populate(this.codexFile);
            asf.ShowDialog(this);
        }

        public void RecalculateTotal() {
            int total = 0;
            foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                if (!(row is CategoryRow)) {
                    foreach (Unit unit in ((ListEntry)row.Tag).Units) {
                        total += unit.GetTotalCost();
                    }
                    total += ((ListEntry)row.Tag).BaseEntry.CostOffset;
                }
            }
            this.toolStripLabelTotal.Text = total + " pts";

        }

        public void ShowEntryDetail() {
            if (this.dataGridViewList.SelectedRows.Count == 0) {
                this.labelNoUnitSelected.Text = "No unit selected";
                this.labelNoUnitSelected2.Text = "";
                this.tabControlOptions.TabPages.Clear();
                this.dataGridViewAttributes.Rows.Clear();
            } else {
                if (this.dataGridViewList.SelectedRows[0] is CategoryRow) {
                    this.labelNoUnitSelected.Text = "No unit selected";
                    this.labelNoUnitSelected2.Text = "";
                    this.dataGridViewAttributes.Rows.Clear();
                    this.tabControlOptions.TabPages.Clear();
                } else {
                    ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
                    this.labelNoUnitSelected.Text = entry.BaseEntry.Name;
                    this.labelNoUnitSelected2.Text = "";
                    this.PopulateAttributes();
                }
            }
        }

        public void PopulateAttributes() {
            this.dataGridViewAttributes.Rows.Clear();
            ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
            Dictionary<string, Unit> parsed = new Dictionary<string, Unit>();
            if (entry != null) {
                foreach (Unit unit in entry.Units) {
                    if (!parsed.ContainsKey(unit.Name)) {
                        AttributeRow row = new AttributeRow();
                        row.Tag = unit;
                        row.Unit = unit;
                        row.Height = 46;
                        row.Cells.Add(new NiceRenderer("000"));
                        row.Cells[0].ToolTipText = unit.GetEquippedString();
                        this.dataGridViewAttributes.Rows.Add(row);
                        parsed.Add(unit.Name, unit);
                    }
                }
            }
        }

        private void dataGridViewList_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
            this.RecalculateTotal();
        }

        private void dataGridViewList_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) {
            this.RecalculateTotal();
        }

        private void dataGridViewList_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e) {
            this.RecalculateTotal();
        }

        private void dataGridViewList_SelectionChanged(object sender, EventArgs e) {
            this.ShowEntryDetail();
            //this.PopulateAttributes();
        }

        private void dataGridViewAttributes_SelectionChanged(object sender, EventArgs e) {
            if (this.dataGridViewAttributes.SelectedRows.Count > 0) {
                Unit unit = (Unit)this.dataGridViewAttributes.SelectedRows[0].Tag;
                if (unit != null) {
                    ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
                    Console.WriteLine(unit.Name);
                    Console.WriteLine(unit.GetEquippedString());
                    this.labelNoUnitSelected2.Text = unit.Name;
                    this.PopulateWargearPanel(unit.Name, unit, entry);
                    this.ValidateAddDeleteButtons();
                }
            }
        }
        public void ValidateAddDeleteButtons() {
            if (this.dataGridViewAttributes.SelectedRows.Count > 0) {
                Unit unit = (Unit)this.dataGridViewAttributes.SelectedRows[0].Tag;
                if (unit != null) {
                    ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
                    this.labelNoUnitSelected2.Text = unit.Name;
                    this.PopulateWargearPanel(unit.Name, unit, entry);
                    int count = 0;
                    foreach (Unit existing in entry.Units) {
                        if (existing.Name == unit.Name) {
                            count++;
                        }
                    }
                    this.toolStripButtonAdd.Enabled = count < unit.Maximum;
                    this.toolStripButtonDelete.Enabled = count > unit.Minimum;
                }
            } else {
                this.toolStripButtonDelete.Enabled = this.toolStripButtonAdd.Enabled = false;
            }
        }

        public void PopulateWargearPanel(string unitName, Unit unit, ListEntry entry) {
            for (int i = 0; i < this.tabControlOptions.TabPages.Count; i++)
            {
                this.tabControlOptions.TabPages[i].Dispose();
            }
            this.tabControlOptions.TabPages.Clear();
            if (unit != null) {
                Dictionary<string, TabPage> tabNames = new Dictionary<string, TabPage>();
                Dictionary<TabPage, List<Control>> controls = new Dictionary<TabPage, List<Control>>();

                foreach (Equipment equipment in unit.OptionalEquipment) {
                    if (!equipment.Fixed) {
                        TabPage page = null;
                        try {
                            if (!tabNames.ContainsKey("Equipment")) { //equipment.Wargear.Type)) {
                                page = new TabPage("Equipment");//equipment.Wargear.Type);
                                this.tabControlOptions.TabPages.Add(page);
                                tabNames.Add("Equipment", page);//equipment.Wargear.Type, page);
                            } else {
                                page = tabNames["Equipment"];//equipment.Wargear.Type];
                            }
                            if (!equipment.Toggle) {
                                QuantityWargearControl qwc = new QuantityWargearControl(page);
                                qwc.Populate(unitName, entry, equipment.Wargear);
                                List<Control> controlEntry = null;
                                if (!controls.ContainsKey(page)) {
                                    controlEntry = new List<Control>();
                                } else {
                                    controlEntry = controls[page];
                                }
                                qwc.Tag = equipment.Wargear.Type;
                                controlEntry.Add(qwc);
                                controls[page] = controlEntry;
                            } else {
                                ToggleWargearControl qwc = new ToggleWargearControl(page);
                                qwc.Unit = unit;
                                qwc.ListEntry = entry;
                                qwc.Wargear = equipment.Wargear;
                                qwc.Tag = equipment.Wargear.Type;
                                qwc.Populate();
                                List<Control> controlEntry = null;
                                if (!controls.ContainsKey(page)) {
                                    controlEntry = new List<Control>();
                                } else {
                                    controlEntry = controls[page];
                                }
                                controlEntry.Add(qwc);
                                controls[page] = controlEntry;
                            }
                        } catch { }
                    }
                }

                foreach (ReplacementGroup group in unit.ReplacementGroups) {
                    TabPage page = null;
                    foreach (TabPage p in controls.Keys) {
                        foreach (Control c in controls[p]) {
                            if (c is QuantityWargearControl) {
                                if (((QuantityWargearControl)c).Wargear.Name == group.Default.Wargear.Name) {
                                    page = p;
                                    break;
                                }
                            }
                        }
                        if (page != null) {
                            break;
                        }
                    }
                    if (page == null) {
                        throw new Exception("Could not find attribute page for replacement group");
                    }

                    page.Paint += new PaintEventHandler(page_Paint);
                    foreach (Equipment replacementEquipment in group.Options) {
                        QuantityWargearControl qwc = new QuantityWargearControl(page);
                        qwc.Populate(unitName, entry, replacementEquipment.Wargear);
                        List<Control> controlEntry = null;
                        if (!controls.ContainsKey(page)) {
                            controlEntry = new List<Control>();
                        } else {
                            controlEntry = controls[page];
                        }
                        qwc.Tag = replacementEquipment.Wargear.Type;
                        controlEntry.Add(qwc);
                        controls[page] = controlEntry;
                    }
                    foreach (DistinctEntry distinctEntry in group.DistinctEntries) {
                        foreach (Equipment replacementEquipment in distinctEntry.Options) {
                            QuantityWargearControl qwc = new QuantityWargearControl(page);
                            qwc.Populate(unitName, entry, replacementEquipment.Wargear);
                            qwc.Tag = replacementEquipment.Wargear.Type;
                            List<Control> controlEntry = null;
                            if (!controls.ContainsKey(page)) {
                                controlEntry = new List<Control>();
                            } else {
                                controlEntry = controls[page];
                            }
                            page.Text = "Equipment";
                            page.Scroll += new ScrollEventHandler(page_Scroll);
                            controlEntry.Add(qwc);
                            controls[page] = controlEntry;
                        }
                    }
                }
                this.tabControlOptions.Visible = false;
                foreach (TabPage page in controls.Keys) {                   
                    List<Control> controlEntries = controls[page];
                    List<string> cats = new List<string>();
                    Dictionary<string, List<Control>> organised = new Dictionary<string, List<Control>>();
                    foreach (Control c in controlEntries) {
                        List<Control> ocontrols = new List<Control>();
                        if (organised.ContainsKey(c.Tag.ToString())) {
                            ocontrols = organised[c.Tag.ToString()];
                        } else {
                            WargearHeaderControl l = new WargearHeaderControl();
                            l.Font = new Font(l.Font, FontStyle.Bold);
                            l.Text = c.Tag.ToString();
                            ocontrols.Add(l);
                            cats.Add(c.Tag.ToString());
                        }
                        ocontrols.Add(c);
                        organised[c.Tag.ToString()] = ocontrols;
                    }

                    cats.Sort();
                    cats.Reverse();
                    page.AutoScroll = true;
                    foreach (string category in cats) {
                        organised[category].Reverse();
                        foreach (Control control in organised[category]) {
                            control.Dock = DockStyle.Top;
                            control.BackColor = Color.Transparent;
                            bool add = true;
                            if (add) {
                                page.Controls.Add(control);
                            }
                        }
                    }
                }
                this.tabControlOptions.Visible = true;
            }
        }
        void page_Paint(object sender, PaintEventArgs e) {
            /*TabPage p = (TabPage)sender;
            try {
                System.Drawing.Drawing2D.LinearGradientBrush lgb = new System.Drawing.Drawing2D.LinearGradientBrush(
                    new Rectangle(0, 0, p.Width, p.Height),
                    SystemColors.Control,
                    SystemColors.ControlLightLight,
                    270
                    );
                e.Graphics.FillRectangle(lgb, 0, 0, p.Width, p.Height);
                e.Graphics.DrawRectangle(SystemPens.ControlDarkDark, 0, 0, p.Width-1, p.Height-1);
            } catch { }*/
        }

        void page_Scroll(object sender, ScrollEventArgs e) {
            /*foreach (Control c in ((TabPage)sender).Controls) {
                if (c is WargearHeaderControl) {
                    c.Invalidate(true);
                }
            }*/
        }

        private void listViewCodexEntries_DoubleClick(object sender, EventArgs e) {
            if (this.listViewCodexEntries.SelectedItems.Count > 0) {
                this.AddEntry((CodexEntry)this.listViewCodexEntries.SelectedItems[0].Tag);
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e) {
            this.DeleteSelected();
        }

        private void toolStripButtonAdd_Click(object sender, EventArgs e) {
            if (this.dataGridViewAttributes.SelectedRows.Count > 0) {
                Unit unit = (Unit)this.dataGridViewAttributes.SelectedRows[0].Tag;
                ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
                List<Equipment> toggleEquipment = new List<Equipment>();
                int count = 0;
                foreach (Unit existing in entry.Units) {
                    if (unit.Name == existing.Name) {
                        count++;
                    }
                }

                // Search for toggled equipment on that unit type.
                foreach (Unit existing in entry.Units)
                {
                    if (unit.Name == existing.Name)
                    {
                        foreach (Equipment eq in existing.Equipped)
                        {
                            if (eq.Toggle)
                            {
                                toggleEquipment.Add(eq);
                            }
                        }
                        break;
                    }
                }

                if (count < unit.Maximum) {
                    for (int i = 0; i < unit.Increment;i++ ) {
                        Unit n = Unit.Copy(unit);
                        foreach (Equipment eq in toggleEquipment)
                        {
                            n.Equipped.Add(eq);
                        }
                        entry.Units.Add(n);
                        entry.UpdateRow();
                    }
                    this.dataGridViewList.Invalidate(true);
                    this.RecalculateTotal();
                    this.ValidateAddDeleteButtons();
                }
            }
        }


        private void toolStripButtonDelete_Click(object sender, EventArgs e) {
            if (this.dataGridViewAttributes.SelectedRows.Count > 0) {
                Unit unit = (Unit)this.dataGridViewAttributes.SelectedRows[0].Tag;
                ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
                for (int i = 0; i < unit.Increment; i++) {
                    int count = 0;
                    Unit last = null;
                    foreach (Unit existing in entry.Units) {
                        if (unit.Name == existing.Name) {
                            last = existing;
                            count++;
                        }
                    }
                    if (count > unit.Minimum && last != null) {
                        entry.Units.Remove(last);
                        entry.UpdateRow();
                    }

                    if (count == 1) {
                        this.PopulateAttributes();
                    }
                }
                this.dataGridViewList.Invalidate(true);
                this.RecalculateTotal();
                this.ValidateAddDeleteButtons();
            }
        }

        private void newListToolStripMenuItem_Click(object sender, EventArgs e) {
            this.CreateNewList();
        }

        private void toolStripButtonNew_Click(object sender, EventArgs e) {
            this.CreateNewList();
        }

        public void CreateNewList() {
            NewListForm nlf = new NewListForm();
            DialogResult dr = nlf.ShowDialog(this);
            if (dr == DialogResult.OK) {
                this.LoadCodex(nlf.SelectedCodex.Path);
                this.codexFile.UserListName = nlf.ListName;
                this.listNameBox.Text = nlf.ListName;
                this.listNameBox.ReadOnly = false;
                this.ValidateList();
            }
        }

        public void Save() {
            bool empty = true;
            foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                if (! (row is CategoryRow) ) {
                    empty = false;
                    break;
                }
            }
            if (empty) {
                MessageBox.Show(
                    this,
                    "It doesn't make sense to save an empty file",
                    "Empty list",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Stop
                    );
                return;
            }

            DialogResult dr = this.saveFileDialog.ShowDialog(this);
            if (dr == DialogResult.OK) {
                string filename = this.saveFileDialog.FileName;
                List<DataGridViewRow> rows = new List<DataGridViewRow>();
                foreach (DataGridViewRow row in this.dataGridViewList.Rows) {
                    if (! ( row is CategoryRow) ) {
                        rows.Add(row);
                    }
                }
                BodgerFile bf = new BodgerFile();
                bf.Save(filename,this.codexFile,rows);
            }
        }

        public void Load(string filename) {
            BodgerFile bf = new BodgerFile();
            bf.Load(filename, this.dataGridViewList, this);
            this.toolStripLabelName.Text = this.codexFile.Name;
            this.listNameBox.Text = codexFile.UserListName;
            this.listNameBox.ReadOnly = false;
        }

        public void Load() {
            DialogResult dr = this.openFileDialog.ShowDialog(this);
            if (dr == DialogResult.OK) {
                this.Load(this.openFileDialog.FileName);
            }
        }

        public void Print() {
            if (this.codexFile == null)
            {
                MessageBox.Show("No codex is loaded to print.", "Print Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            PrintPreviewForm pvf = new PrintPreviewForm(this.codexFile, this.dataGridViewList);
            pvf.Show();
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) {
            this.Save();
        }

        private void toolStripButtonSaveAs_Click(object sender, EventArgs e) {
            this.Save();
        }

        private void toolStripButtonOpen_Click(object sender, EventArgs e) {
            this.Load();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e) {
            this.Load();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
            Application.Exit();
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e) {
            this.Print();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
            MessageBox.Show(
                this,
                "ArmyBodger 2 Beta 2\n\n(c)2009 richyp.com",
                "About"
                );
        }

        public string GenerateForumsCode(ForumsCodeOptions fco) {
            if (this.codexFile == null)
            {
                return "No codex file loaded.";
            }

            int unitNumber = 1;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(this.codexFile.UserListName + ": " + this.toolStripLabelTotal.Text);
            foreach (DataGridViewRow row in this.dataGridViewList.Rows)
            {
                if (!(row is CategoryRow))
                {
                    ListEntry entry = (ListEntry)row.Tag;
                    sb.Append(unitNumber + ". " + entry.BaseEntry.Name);
                    sb.AppendLine(" (" + entry.GetTotalCost() + "pts)");

                    string lastUnit = entry.Units[0].Name;
                    int modelCount = 0;
                    Dictionary<string, Equipment> equipmentNameList = new Dictionary<string, Equipment>();
                    Dictionary<Equipment, int> equipmentList = new Dictionary<Equipment, int>();

                    for (int i = 0; i < entry.Units.Count; i++)
                    {
                        if (lastUnit == entry.Units[i].Name)
                        {
                            modelCount++;
                        }
                        else
                        {
                            PrintModelsForumsCode(ref sb, ref fco, ref entry, i, ref modelCount, ref lastUnit, ref equipmentList);
                            equipmentNameList.Clear();
                        }
                        foreach (Equipment eq in entry.Units[i].Equipped)
                        {
                            bool display = true;
                            foreach (Equipment def in entry.Units[i].AllWargear)
                            {
                                if (def.Wargear.Name == eq.Wargear.Name)
                                {
                                    if ((fco.ShowFixedWargear == false && def.Fixed) || (fco.ShowDefaultWargear == false && def.Default))
                                    {
                                        display = false;
                                        break;
                                    }
                                }
                            }

                            if (!display)
                                continue;

                            if (equipmentNameList.ContainsKey(eq.Wargear.Name))
                            {
                                equipmentList[equipmentNameList[eq.Wargear.Name]]++;
                            }
                            else
                            {
                                equipmentNameList.Add(eq.Wargear.Name, eq);
                                equipmentList.Add(eq, 1);
                            }
                        }
                        if (i == entry.Units.Count - 1)
                        {
                            PrintModelsForumsCode(ref sb, ref fco, ref entry, i, ref modelCount, ref lastUnit, ref equipmentList);
                            equipmentNameList.Clear();
                        }
                    }
                    unitNumber++;
                }
                else
                {
                    string category = ((CategoryRow)row).Category;
                    category = category.Substring(category.IndexOf('.') + 1);
                    sb.AppendLine();
                    sb.Append("----- " + category + " -");
                    for (int i = 8 + category.Length; i < 40; i++)
                    {
                        sb.Append("-");
                    }
                    sb.AppendLine();

                    unitNumber = 1;
                }
            }

            if (fco.UseNBSP)
            {
                sb.Replace(" ", "&nbsp;");
            }

            return sb.ToString();
        }

        private void PrintModelsForumsCode(ref StringBuilder sb, ref ForumsCodeOptions fco, ref ListEntry entry, int i, ref int modelCount, ref string lastUnit, ref Dictionary<Equipment, int> equipmentList)
        {
            string tabLine = "   ";

            if (entry.Units.Count == 1 && entry.Units[i].Name == entry.BaseEntry.Name)
            {
                tabLine = " ";
            }
            else
            {
                sb.AppendLine(tabLine + "- " + modelCount + "x " + lastUnit);
            }

            if (equipmentList.Count > 0)
            {
                sb.Append(tabLine + "  - ");
                foreach (Equipment eq in equipmentList.Keys)
                {
                    sb.Append(equipmentList[eq] + "x " + eq.Wargear.Name);
                    if (!fco.HideIndividualPointCosts)
                    {
                        sb.Append(" (" + (equipmentList[eq] * eq.Cost).ToString() + "pts)");
                    }
                    sb.Append(", ");
                }
                sb.Remove(sb.Length - 2, 2);
                sb.AppendLine();
            }

                
            //}

            lastUnit = entry.Units[i].Name;
            modelCount = 1;
            equipmentList.Clear();
        }

        private void saveEntryAsTemplateToolStripMenuItem_Click(object sender, EventArgs e) {
            SaveTemplateForm stf = new SaveTemplateForm();
            ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
            stf.Populate(entry);
            stf.StartPosition = FormStartPosition.CenterParent;
            DialogResult dr = stf.ShowDialog(this);
            if (dr == DialogResult.OK && stf.TemplateName.Length > 0) {
                if (System.IO.File.Exists(Application.StartupPath + "/templates/" + stf.TemplateName + ".xml")) {
                    dr = MessageBox.Show(
                        this,
                        "A template with that name already exists.\nOverwrite it?",
                        "Duplicate Template Name",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Warning
                        );
                    if (dr == DialogResult.No) {
                        return;
                    }
                }
                System.IO.StreamWriter output = new System.IO.StreamWriter(
                    Application.StartupPath + "/templates/" + stf.TemplateName + ".xml"
                    );
                output.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                output.WriteLine("<template>");
                output.WriteLine("  <codex>" + this.codexFile.Name + "</codex>");
                output.WriteLine("  <base>" + entry.BaseEntry.Name + "</base>");
                output.WriteLine("  <label>" + stf.TemplateName + "</label>");
                output.WriteLine("  <entry>");
                foreach (Unit unit in entry.Units) {
                    output.WriteLine("      <unit>");
                    output.WriteLine("         <name>" + unit.Name + "</name>");
                    foreach (Equipment eq in unit.Equipped) {
                        output.WriteLine("         <wargear>" + eq.Wargear.Name + "</wargear>");
                    }
                    output.WriteLine("      </unit>");
                }
                output.WriteLine("  </entry>");
                output.WriteLine("</template>");
                output.Flush();
                output.Close();

                PopulateTemplates();
            }
        }

        private void showSpecialCharactersToolStripMenuItem_Click(object sender, EventArgs e) {
            if (!this.showSpecialCharactersToolStripMenuItem.Checked)
            {
                List<DataGridViewRow> deleatedRows = new List<DataGridViewRow>();

                foreach (DataGridViewRow row in dataGridViewList.Rows)
                {
                    if (row is CategoryRow)
                        continue;
                    ListEntry entry = (ListEntry)row.Tag;
                    if (entry.BaseEntry.Special)
                        deleatedRows.Add(row);
                }

                foreach (DataGridViewRow row in deleatedRows)
                {
                    dataGridViewList.Rows.Remove(row);
                }
            }

            this.PopulateCodexEntries(false);
        }

        private void generateForumsCodeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ForumsCodeForm fcf = new ForumsCodeForm(this);
            fcf.Show();
            //fcf.Dispose();
        }

        private void toolStripButtonMove_Click(object sender, EventArgs e)
        {
            ListEntry entry = (ListEntry)this.dataGridViewList.SelectedRows[0].Tag;
            string newCategory = entry.AlternateCategory;

            this.DeleteSelected();
            this.AddEntry(entry, entry.AlternateCategory);
            entry.AlternateCategory = entry.CurrentCategory;
            entry.CurrentCategory = newCategory;

        }

        private void listViewCodexEntries_Resize(object sender, EventArgs e)
        {
            listViewCodexEntries.Columns[0].Width = listViewCodexEntries.Size.Width - 52;
        }

        private void listViewTemplates_DoubleClick(object sender, EventArgs e)
        {
            if (this.listViewTemplates.SelectedItems.Count > 0)
            {
                ListEntry templateEntry = (ListEntry)this.listViewTemplates.SelectedItems[0].Tag;
                ListEntry newEntry = new ListEntry(templateEntry.BaseEntry, dataGridViewList);
                newEntry.Units.Clear();
                foreach (Unit unit in templateEntry.Units)
                {
                    Unit newUnit = Unit.Copy(unit);
                    newUnit.Equipped.Clear();
                    foreach (Equipment eq in unit.Equipped)
                    {
                        newUnit.Equipped.Add(Equipment.Copy(eq));
                    }
                    newEntry.Units.Add(newUnit);
                    

                }
                newEntry.UpdateRow();

                this.AddEntry(newEntry, newEntry.CurrentCategory);
            }
        }

        private void listNameBox_TextChanged(object sender, EventArgs e)
        {
            this.codexFile.UserListName = listNameBox.Text;
        }
     
    }
}
